package com.jiajiakang.util.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * JSON工具类
 *
 * @author ljk
 * @since 2024/2/1 9:54
 */
public class JsonUtil {
    private static final ObjectMapper MAPPER;

    static {
        MAPPER = new ObjectMapper()
                //设置时区格式
                .setLocale(Locale.CHINA)
                //设置时区
                .setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()))
                //简化字段显示
                .setSerializationInclusion(JsonInclude.Include.NON_DEFAULT)
                //未知属性报错
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        SimpleModule javaTimeModule = new SimpleModule();
        //日期序列化
        String dateTimePattern = "yyyy-MM-dd HH:mm:ss";
        String datePattern = "yyyy-MM-dd";
        String timePattern = "HH:mm:ss";
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimePattern)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(datePattern)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(timePattern)));
        javaTimeModule.addSerializer(Date.class, new DateSerializer(false, new SimpleDateFormat(dateTimePattern)));
        //日期反序列化
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimePattern)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(datePattern)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timePattern)));
        javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer(new DateDeserializers.DateDeserializer(), new SimpleDateFormat(dateTimePattern), null));
        MAPPER.registerModule(javaTimeModule);
    }

    /**
     * 对象转成JSON字符串,忽略掉为null的属性
     *
     * @param data 实体类
     * @return json
     * @author ljk
     * @since 2022/9/22 9:53
     */
    public static String toJson(Object data) {
        if (data == null) {
            return null;
        }
        try {
            return MAPPER.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            System.err.println("实体类转JSON异常,数据为:" + data);
        }
        return null;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param json json数据
     * @param type jackson的类型
     */
    public static <T> T parseJson(String json, TypeReference<T> type) {
        try {
            return MAPPER.readValue(json, type);
        } catch (Exception e) {
            System.err.println("json序列化前:" + json);
            throw new RuntimeException(String.format("JSON序列化字段失败,错误原因:%s", e.getMessage()), e);
        }
    }

    /**
     * 将json结果集转化为对象
     *
     * @param json     json数据
     * @param beanType 对象中的object类型
     */
    public static <T> T parseJson(String json, Class<T> beanType) {
        try {
            return MAPPER.readValue(json, beanType);
        } catch (Exception e) {
            System.err.println("json序列化前:" + json);
            throw new RuntimeException(String.format("JSON序列化字段失败,错误原因:%s", e.getMessage()), e);
        }
    }

    /**
     * 将json结果集转化为Map对象
     *
     * @param json json数据
     */
    @SuppressWarnings(value = "unchecked")
    public static Map<String, Object> parseJson(String json) {
        try {
            return MAPPER.readValue(json, Map.class);
        } catch (Exception e) {
            System.err.println("json序列化前:" + json);
            throw new RuntimeException(String.format("JSON序列化字段失败,错误原因:%s", e.getMessage()), e);
        }
    }

    /**
     * desc: 字符串转JSONNode
     *
     * @param json json字符串
     * @return JsonNode
     * @author ljk
     * @date 2021/9/13 16:06
     */
    public static JsonNode parseJson2Node(String json) {
        try {
            return MAPPER.readTree(json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(String.format("JSON读取字符串失败,原文[%s]", json));
        }
    }


    /**
     * 根据 节点 获取 JSON 中的数据
     *
     * @param nodeName 节点名称，使用 . 分隔
     * @param json     JSON字符串
     * @return 返回 JSON 中的数据
     * @throws JsonProcessingException 读取 JSON 异常
     */

    public static JsonNode findJsonNode(String json, String nodeName) {
        if (nodeName == null || nodeName.isEmpty()) {
            return null;
        }
        try {
            JsonNode jsonNode = MAPPER.readTree(json);
            return findJsonNode(jsonNode, nodeName);
        } catch (Exception e) {
            throw new RuntimeException(String.format("JSON解析异常,异常信息为:[%s]", e.getMessage()), e);
        }
    }


    /**
     * 根据 节点 获取 JSON 中的数据
     *
     * @param nodeName 节点名称，使用 . 分隔
     * @param json     JSON 数据
     * @return 返回 JSON 中的数据
     */
    public static JsonNode findJsonNode(JsonNode json, String nodeName) {
        if (nodeName.contains(".")) {
            for (String name : nodeName.split("\\.")) {
                json = json.get(name);
                if (json == null) {
                    return null;
                }
            }
            return json;
        } else {
            return json.get(nodeName);
        }

    }

    /**
     * 查找json的节点并返回节点的字符串内容
     *
     * @param json jsonNode
     * @param id 节点编码
     * @return 节点的值
     * @author ljk
     * @since 2024/2/1 13:47
     */
    public static String findJsonNode2String(JsonNode json, String id) {
        JsonNode node = findJsonNode(json, id);
        return node != null ? node.asText() : null;
    }

    /**
     * 查找json的节点并返回节点的字符串内容
     *
     * @param json json
     * @param id 节点编码
     * @return 节点的字符串内容
     * @author ljk
     * @since 2024/2/1 13:47
     */
    public static String findJsonNode2String(String json, String id) {
        JsonNode node = findJsonNode(json, id);
        return node != null ? node.asText() : null;
    }
}
